home *** CD-ROM | disk | FTP | other *** search
/ Maclife 42 / MACLIFE42.ISO.7z / MACLIFE42.ISO / FreeWare200 / 圧縮伸張⁄コード / MacGzip / MacGzip 1.1.2 Source.sea / MacGzip 1.1.2 Source / Mac / GetFolder.c < prev    next >
Text File  |  1997-04-01  |  9KB  |  369 lines

  1. /*    StandardGetFolder example
  2.  
  3.     Steve Falkenburg -- MacDTS
  4.     
  5.     This sample uses the new System 7 CustomGetFile routine
  6.     to provide a StandardGetFolder call to be used by applications
  7.     when the user needs to select a folder instead of a file.
  8.     
  9.     It's written in Think C, but should work in MPW if a few #include
  10.     files are added.
  11.     
  12.     The style of the dialog box is taken from the Human Interface note
  13.     on folder selection.
  14.     
  15.     SJF        5/2/92        added check for empty filename and call to MakeFSSpec
  16.     SJF        5/2/92        added check for refcon in filter and hook routines
  17.     SJF        10/30/91    original coding
  18.     SPD        8/14/95        UPP and minor changes
  19.     
  20. */
  21.  
  22. #include <Folders.h>
  23. #include <Aliases.h>
  24.  
  25. #include "GzPStrings.h"
  26.  
  27. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  28. #  define CreateRoutineDescriptor(info, proc)                                    ¥
  29.         RoutineDescriptor g##proc##RD = BUILD_ROUTINE_DESCRIPTOR(info, proc)
  30. #  define GetRoutineAddress(proc)    (&g##proc##RD)
  31. #else
  32. #  define GetRoutineAddress(proc)    proc
  33. #endif
  34.  
  35. /* prototypes */
  36.  
  37. Boolean SFGetFolder(FSSpec *fSpec);
  38.  
  39. static void InitStuff(void);
  40. static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
  41. static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
  42. static void HitButton(DialogPtr theDlg,short item);
  43. static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
  44. static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
  45. static Boolean SameFile(FSSpec *file1,FSSpec *file2);
  46. static Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
  47. static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
  48. static OSErr MakeCanonFSSpec(FSSpec *fSpec);
  49. static Boolean ShouldHiliteSelect(FSSpec *fSpec);
  50.  
  51. /* typedefs */
  52.  
  53. typedef struct {
  54.     StandardFileReply *replyPtr;
  55.     FSSpec oldSelection;
  56. } SFData, *SFDataPtr;
  57.  
  58. /* constants */
  59.  
  60. #define    kSelectItem            10
  61. #define    kSFDlg                129
  62. #define    kCanSelectDesktop    true
  63. #define    kSelectStrRsrc        128
  64. #define kDefaultSelectString "¥pSelect"
  65. #define    kDeskStrRsrc        129
  66. #define    kDefaultDeskString    "¥pDesktop"
  67. #define    kSelectKey            's'
  68.  
  69. /* globals */
  70.  
  71. FSSpec gDeskFolderSpec;
  72. Str255 gSelectString;
  73. Str255 gDesktopFName;
  74.  
  75. /*
  76.  * Usage:
  77.  *    FSSpec fSpec;
  78.  *    Boolean good;
  79.  *
  80.  *  extern Boolean SFGetFolder(FSSpec *fSpec);
  81.  *    good = SFGetFolder(&fSpec);
  82.  */
  83.  
  84.  
  85. /* initialize managers */
  86.  
  87. static void InitStuff(void)
  88. {
  89.     Handle strHndl;
  90.         
  91.     strHndl = Get1Resource('STR ',kSelectStrRsrc);
  92.     if (ResError()!=noErr || !strHndl || !*strHndl)
  93.         BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
  94.     else
  95.     {
  96.         BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
  97.         ReleaseResource(strHndl);
  98.     }
  99.  
  100.     strHndl = Get1Resource('STR ',kDeskStrRsrc);
  101.     if (ResError()!=noErr || !strHndl || !*strHndl)
  102.         BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
  103.     else
  104.     {
  105.         BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
  106.         ReleaseResource(strHndl);
  107.     }
  108. }
  109.  
  110.  
  111. /* do getfile */
  112.  
  113. Boolean SFGetFolder(FSSpec *fSpec)
  114. {
  115.     Point                where = {-1,-1};
  116.     StandardFileReply    sfReply;
  117.     SFData                sfUserData;
  118.     OSErr                err;
  119.     Boolean                targetIsFolder,
  120.                         wasAliased;
  121.     
  122. #if GENERATINGCFM || USESROUTINEDESCRIPTORS
  123.     CreateRoutineDescriptor(uppFileFilterYDProcInfo, FilterAllFiles);
  124.     CreateRoutineDescriptor(uppDlgHookYDProcInfo, MyDlgHook);
  125.     CreateRoutineDescriptor(uppModalFilterYDProcInfo, MyModalFilter);
  126. #endif
  127.     
  128.     InitStuff();
  129.  
  130. /* initialize user data area */
  131.     
  132.     sfUserData.replyPtr = &sfReply;
  133.     sfUserData.oldSelection.vRefNum = -9999;    /* init to ridiculous value */
  134.     
  135.     CustomGetFile(
  136.                     (FileFilterYDUPP)GetRoutineAddress(FilterAllFiles),
  137.                     -1,nil,
  138.                     &sfReply,
  139.                     kSFDlg,
  140.                     where,
  141.                     (DlgHookYDUPP)GetRoutineAddress(MyDlgHook),
  142.                     (ModalFilterYDUPP)GetRoutineAddress(MyModalFilter),
  143.                     nil,nil,&sfUserData);
  144.     
  145.     
  146.     if (sfReply.sfGood)
  147.     {
  148.         MakeCanonFSSpec(&sfReply.sfFile); /* spd, August 29, 1995 */
  149.         
  150.         err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
  151.         if (err!=noErr)
  152.             return false;
  153.     }
  154.     
  155.     err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
  156.     if (err!=noErr)
  157.         return false;
  158.     
  159.     return sfReply.sfGood;
  160. }
  161.  
  162.  
  163. /*    this dialog hook checks the contents of the additional edit fields
  164.     when the user selects a file.  The focus of the dialog is changed if one
  165.     of the fields is out of range.
  166. */
  167.  
  168. static pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
  169. {
  170.     SFDataPtr sfUserData;
  171.     FSSpec curSpec;
  172.     OSType refCon;
  173.     
  174.     refCon = GetWRefCon(theDlg);
  175.     if (refCon!=sfMainDialogRefCon)
  176.         return item;
  177.         
  178.     sfUserData = (SFDataPtr) userData;
  179.     
  180.     if (item==sfHookFirstCall || item==sfHookLastCall)
  181.         return item;
  182.     
  183.     if (item==sfItemVolumeUser) {
  184.         sfUserData->replyPtr->sfFile.name[0] = '¥0';
  185.         sfUserData->replyPtr->sfFile.parID = 2;
  186.         sfUserData->replyPtr->sfIsFolder = false;
  187.         sfUserData->replyPtr->sfIsVolume = false;
  188.         sfUserData->replyPtr->sfFlags = 0;
  189.         item = sfHookChangeSelection;
  190.     }
  191.         
  192.     if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
  193.         BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
  194.         MakeCanonFSSpec(&curSpec);
  195.         
  196.         if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
  197.             GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);    
  198.         SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
  199.         
  200.         BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
  201.     }
  202.     
  203.     if (item==kSelectItem)
  204.         item = sfItemOpenButton;
  205.         
  206.     return item;
  207. }
  208.  
  209.  
  210. static pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
  211. {
  212. #pragma unused(myData)
  213.  
  214.     Boolean evHandled;
  215.     char keyPressed;
  216.     OSType refCon;
  217.     
  218.     refCon = GetWRefCon(theDlg);
  219.     if (refCon!=sfMainDialogRefCon)
  220.         return false;
  221.         
  222.     evHandled = false;
  223.     
  224.     switch (ev->what)
  225.     {
  226.         case keyDown:
  227.         case autoKey:
  228.             keyPressed = ev->message & charCodeMask;
  229.             if ((ev->modifiers & cmdKey) != 0)
  230.             {
  231.                 switch (keyPressed)
  232.                 {
  233.                     case kSelectKey:
  234.                         HitButton(theDlg,kSelectItem);
  235.                         *itemHit = kSelectItem;
  236.                         evHandled = true;
  237.                         break;
  238.                 }
  239.             }
  240.             break;
  241.     }
  242.     
  243.     return evHandled;
  244. }
  245.  
  246.  
  247. static void HitButton(DialogPtr theDlg,short item)
  248. {
  249.     short iType;
  250.     ControlHandle iHndl;
  251.     Rect iRect;
  252.     long fTicks;
  253.     
  254.     GetDialogItem(theDlg,item,&iType,(Handle *)&iHndl,&iRect);
  255. #ifndef THINK_C                               
  256.     HiliteControl(iHndl, kControlButtonPart);
  257. #else
  258.     HiliteControl(iHndl, inButton);
  259. #endif
  260.     Delay(5,&fTicks);
  261.     HiliteControl(iHndl,0);
  262. }
  263.  
  264.  
  265. static pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
  266. {
  267. #pragma unused(myDataPtr)
  268.  
  269.     if (pb->hFileInfo.ioFlAttrib & (1<<4))    /* file is a directory */
  270.         return false;
  271.  
  272.     return true;
  273. }
  274.  
  275.  
  276. static void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
  277. {
  278.     short iType;
  279.     Handle iHndl;
  280.     Rect iRect;
  281.     Str255 storeName,tempLenStr,tempSelName;
  282.     short btnWidth;
  283.     
  284.     BlockMove(selName,tempSelName,selName[0]+1);
  285.     GetDialogItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  286.     
  287.     /* truncate select name to fit in button */
  288.     
  289.     btnWidth = iRect.right - iRect.left;
  290.     BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
  291.     PStrCat(tempLenStr, "¥p メモ  ");
  292.     btnWidth -= StringWidth(tempLenStr);
  293.     TruncString(btnWidth,tempSelName,smTruncMiddle);
  294.     
  295.     BlockMove(gSelectString,storeName,gSelectString[0]+1);
  296.  
  297.  
  298.     PStrCat( storeName, "¥p メ");
  299.     PStrCat( storeName, tempSelName);
  300.     PStrCat( storeName, "¥pモ");
  301.  
  302.     SetControlTitle((ControlHandle)iHndl,storeName);
  303.     
  304.     SetDialogItem(theDlg,kSelectItem,iType,iHndl,&iRect);
  305.  
  306.     if (hilited)
  307.         HiliteControl((ControlHandle)iHndl,0);
  308.     else
  309.         HiliteControl((ControlHandle)iHndl,255);        
  310. }
  311.  
  312.  
  313. static Boolean SameFile(FSSpec *file1,FSSpec *file2)
  314. {
  315.     if (file1->vRefNum != file2->vRefNum)
  316.         return false;
  317.     if (file1->parID != file2->parID)
  318.         return false;
  319.     if (!EqualString(file1->name,file2->name,false,true))
  320.         return false;
  321.     
  322.     return true;
  323. }
  324.  
  325.  
  326. static OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
  327. {
  328.     OSErr err;
  329.     
  330.     fSpec->name[0] = '¥0';
  331.     err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
  332.                         &fSpec->vRefNum,&fSpec->parID);
  333.     if (err!=noErr)
  334.         return err;
  335.     
  336.     return MakeCanonFSSpec(fSpec);
  337. }
  338.  
  339.  
  340. static Boolean ShouldHiliteSelect(FSSpec *fSpec)
  341. {
  342.     if (SameFile(fSpec,&gDeskFolderSpec)) {
  343.         BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
  344.         return kCanSelectDesktop;
  345.     }
  346.     else
  347.         return true;
  348. }
  349.  
  350.  
  351. static OSErr MakeCanonFSSpec(FSSpec *fSpec)
  352. {
  353.     DirInfo infoPB;
  354.     OSErr err;
  355.  
  356.     if (fSpec->name[0] != '¥0')
  357.         return noErr;
  358.         
  359.     infoPB.ioNamePtr = fSpec->name;
  360.     infoPB.ioVRefNum = fSpec->vRefNum;
  361.     infoPB.ioDrDirID = fSpec->parID;
  362.     infoPB.ioFDirIndex = -1;
  363.     err = PBGetCatInfoSync((CInfoPBPtr)&infoPB);
  364.     fSpec->parID = infoPB.ioDrParID;
  365.     
  366.     return err;
  367. }
  368.  
  369.